﻿Public Class CronManager
    Private lock As New Object
    Private cronTasks As New Dictionary(Of Guid, iCronTask)
    Private allowCronTasks = True
    Public ReadOnly Property Enabled As Boolean
        Get
            Return Me.allowCronTasks
        End Get
    End Property
    Public ReadOnly Property CronCount As Integer
        Get
            SyncLock Me.lock
                Return Me.cronTasks.Skip(0).Count
            End SyncLock
        End Get
    End Property
    Public ReadOnly Property CronList As List(Of iCronTask)
        Get
            SyncLock Me.lock
                Return Me.cronTasks.Select(Function(x) x.Value).ToList
            End SyncLock
        End Get
    End Property

    Private Sub CronCompleted(sender As iCronTask)
        Log.LogMessage(String.Format("Crontask '{0}' ({1}) completed.", sender.CronName, sender.CronGuid.ToString), LogTypes.Information)
        SyncLock Me.lock
            Me.cronTasks.Remove(sender.CronGuid)
        End SyncLock
    End Sub

    Private Sub CronCanceled(sender As iCronTask)
        Log.LogMessage(String.Format("Crontask '{0}' ({1}) canceled.", sender.CronName, sender.CronGuid.ToString), LogTypes.Information)
        SyncLock Me.lock
            Me.cronTasks.Remove(sender.CronGuid)
        End SyncLock
    End Sub

    Public Sub Consume(crontask As iCronTask)
        If Not Me.allowCronTasks Then
            Log.LogMessage(String.Format("CronManager is disabled, unable to consume the crontask '{0}'.", crontask.CronName), LogTypes.Warning)
            Exit Sub
        End If

        If Not crontask.AllowConcurrent Then
            Dim cronExists As Boolean = False
            SyncLock Me.lock
                cronExists = Me.cronTasks.Values.Any(Function(x) x.CronName = crontask.CronName)
            End SyncLock
            If cronExists Then
                Log.LogMessage(String.Format("The crontask '{0}' cannot be consumed while it is already running.", crontask.CronName), LogTypes.Warning)
                Exit Sub
            End If
        End If

        Log.LogMessage(String.Format("Crontask '{0}' ({1}) is being consumed.", crontask.CronName, crontask.CronGuid.ToString), LogTypes.Information)
        AddHandler crontask.Completed, AddressOf CronCompleted
        AddHandler crontask.Canceled, AddressOf CronCanceled
        crontask.Execute()
        SyncLock Me.lock
            Me.cronTasks.Add(crontask.CronGuid, crontask)
        End SyncLock
    End Sub

    Public Sub Cancel(CronGuid As Guid)
        SyncLock Me.lock
            Me.cronTasks(CronGuid).Cancel()
        End SyncLock
    End Sub

    Public Sub CancelAll()
        SyncLock Me.lock
            For Each ct As iCronTask In Me.cronTasks.Values
                ct.Cancel()
            Next
        End SyncLock
    End Sub

    Public Sub Enable()
        SyncLock Me.lock
            Me.allowCronTasks = True
        End SyncLock
    End Sub

    Public Sub Disable()
        SyncLock Me.lock
            Me.allowCronTasks = False
        End SyncLock
    End Sub

End Class
